package com.sunther.document.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class RedisHelper {

    private static final Logger logger = LoggerFactory.getLogger(RedisHelper.class);

    public static final int CACHE_TIME_1_YEAR = 60 * 60 * 24 * 365;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public Object get(final String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 写入缓存
     */
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key, value);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 写入缓存
     */
    public boolean set(final String key, Object value, int seconds,TimeUnit timeUnit) {
        boolean result = false;
        try {
            if (seconds > 0) {
                redisTemplate.opsForValue().set(key, value, seconds, timeUnit);
            } else {
                redisTemplate.opsForValue().set(key, value);
            }
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 写入缓存
     */
    public boolean set(final String key, Object value, int seconds) {
        boolean result = false;
        try {
            if (seconds > 0) {
                redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(key, value);
            }
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    public boolean exist(final String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 更新缓存
     */
    public boolean getAndSet(final String key, Object value) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().getAndSet(key, value);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 删除缓存
     */
    public boolean delete(final String key) {
        boolean result = false;
        try {
            redisTemplate.delete(key);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 1.Redis设置多个值
     * 命令：HMSET myhash total 15 success 0 time "2019-12-01 11:10:15"
     * 2.当一个任务完成之后，把成功的次数加1
     * 命令：HINCRBY myhash success 1
     * <p>
     * 当前有多少个计算（有点过几次计算）
     * 1.列表中添加值
     * 命令：RPUSH mylist "hello"
     * 2.获取列表中所有元素
     * 命令：LRANGE mylist 0 -1
     */

    /**
     * 设置hash值，同时设置多个属性
     *
     * @param key 键
     * @param map 多个属性值用map封装
     * @return
     */
    public boolean hmset(final String key, Map<String, Object> map) {
        boolean result = false;
        try {
            HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
            opsForHash.putAll(key, map);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 自增值，给hash值某个属性自增
     *
     * @param key   键
     * @param field 要自增的属性
     * @param num   自增值的大小，可以为正数负数
     * @return
     */
    public boolean hincrby(final String key, String field, Integer num) {
        boolean result = false;
        try {
            HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
            opsForHash.increment(key, field, num);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 自增值，给hash值某个属性自增1
     *
     * @param key   键
     * @param field 要自增的属性
     * @return
     */
    public boolean hincrby(final String key, String field) {
        boolean result = false;
        try {
            HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
            opsForHash.increment(key, field, 1);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 获取hash中的所有数据
     *
     * @param key
     * @return
     */
    public Map<Object, Object> hgetall(final String key) {
        Map<Object, Object> entries = new HashMap<>();
        try {
            HashOperations<Object, Object, Object> opsForHash = redisTemplate.opsForHash();
            entries = opsForHash.entries(key);
            return entries;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return entries;
    }

    /**
     * list操作，队列右侧添加值
     *
     * @param key
     * @param value
     * @return
     */
    public boolean rpush(final String key, Object value) {
        boolean result = false;
        try {
            ListOperations<Object, Object> opsForList = redisTemplate.opsForList();
            opsForList.rightPush(key, value);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }

    /**
     * 获取列表中的所有元素
     *
     * @param key
     * @return
     */
    public List<Object> lrange(final String key) {
        List<Object> range = new ArrayList<>();
        try {
            ListOperations<Object, Object> opsForList = redisTemplate.opsForList();
            range = opsForList.range(key, 0, -1);
            return range;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return range;
    }

    /**
     * 删除list中的值
     *
     * @param key   list的key
     * @param value 要删除的list中的value
     * @return
     */
    public boolean lrem(final String key, Object value) {
        boolean result = false;
        try {
            ListOperations<Object, Object> opsForList = redisTemplate.opsForList();
            opsForList.remove(key, 0, value);
            result = true;
        } catch (Exception e) {
            logger.warn("", e);
        }
        return result;
    }


}
